
package com.freeme.cameraplugin.largemode;

import com.freeme.cameraplugin.largemode.R;
import com.freeme.cameraplugin.largemode.ui.LargeModelPreview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import com.freeme.camera.ICameraExt;
import com.freeme.camera.CameraInterfaceManage;

@SuppressLint({
        "InflateParams", "ClickableViewAccessibility"
})
public class LargeModeManager implements View.OnClickListener, View.OnTouchListener {
    private static final String TAG = "LargeModeManager";
    private static final float PREVIEW_FADE_ALPHA = 0.10f;

    public static final int MSG_HIDE_OPERATE_LAYER = 0x001;
    public static final int MSG_SHOW_OPERATE_LAYER = 0x002;
    public static final int MSG_LEAVE_OPERATE_LAYER = 0x003;
    protected static final int MSG_PICTURE_SAVED = 0x004;
    public final int SHOW_TIMEOUT_TIME = 3000;

    private static LargeModeManager instance = null;

    private boolean mIsShowing;

    private LargeModelPreview mLargeModeLayout;
    private ImageView mTopImageMask;
    private ImageView mBottomImageMask;
    private ImageView mVerticalImageTip;
    private RelativeLayout mHScreenLayout;

    private double mFullScreenRatio;
    private View mShutter;
    private LayoutInflater mInflater;
    private ViewGroup mRootView;

    private boolean isOperateLayerShow = false;
    private static final double[] RATIOS = new double[] {
            1.3333, 1.5, 1.6667, 1.7778
    };

    private boolean isViertical = false;
    private Context mContext;
    private ICameraExt mCameraExt;

    public boolean isViertical() {
        return isViertical;
    }

    public void setViertical(boolean isViertical) {
        this.isViertical = isViertical;
    }

    public static final int OUTPUT_IMAGE_WIDTH_IDEAL = 1728;
    public static final int OUTPUT_IMAGE_HEIGHT_IDEAL = 3072;

    private LargeModeManager(Context context, ICameraExt ext) {
        super();

        mContext = context;
        this.mCameraExt = ext;
        mInflater = LayoutInflater.from(mContext);
        mInflater.setFactory(new LayoutInflater.Factory() {
            @Override
            public View onCreateView(String name, Context context, AttributeSet attrs) {
                if ("com.freeme.cameraplugin.largemode.ui.LargeModelPreview".equals(name)) {
                    return new LargeModelPreview(context, attrs);
                }
                return null;
            }
        });
        initFullscreenRatio();
        mWindowManage = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    }

    public static LargeModeManager getInstance(Context context, ICameraExt ext) {
        if (instance == null) {
            instance = new LargeModeManager(context, ext);
        }
        return instance;
    }

    public static void setInstance(LargeModeManager instance) {
        LargeModeManager.instance = instance;
    }

    Handler mHandler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(android.os.Message msg) {
            int what = msg.what;
            switch (what) {
                case MSG_HIDE_OPERATE_LAYER:
                    handOperateHide();
                    break;
                case MSG_SHOW_OPERATE_LAYER:
                    handOperateShow();
                    break;
                case MSG_LEAVE_OPERATE_LAYER:
                    removeMessages(MSG_HIDE_OPERATE_LAYER);
                    break;
                case MSG_PICTURE_SAVED:
                    Log.i(TAG, "[onFileSaved],send MSG_SAVE_THUMBNAIL.");
                    try {
                        Intent intent = new Intent();
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        intent.setAction("com.freeme.largermode.main");
                        Uri uri = (Uri) msg.obj;
                        intent.setData(uri);
                        mCameraExt.getHostContext().startActivity(intent);
                    } catch (Exception e) {
                        Log.i(TAG,
                                "gallery2 is not installed or gallery does not has bigMode feature");
                    }
                    break;
                default:
                    break;
            }
        };
    };
    private WindowManager mWindowManage;

    private void handOperateShow() {
        if (!mIsShowing) {
            return;
        }
        isOperateLayerShow = true;
    }

    private void handOperateHide() {
        if (!mIsShowing || isViertical) {
            return;
        }
        isOperateLayerShow = false;
    }

    public void handUserInteraction() {
        if (isOperateLayerShow) {
            hideOperateLayer();
        }
    }

    @SuppressWarnings("static-access")
    private void startShow(ViewGroup rootView) {
        Log.v(TAG, "startShow");
        mCameraExt = CameraInterfaceManage.getInstance().cameraExt;
        mCameraExt.setBottomBarVisible(View.GONE);
        // mCameraExt.setTopBarBackgroudcolor(0xcc000000);
        findView(rootView);
        addListener();
        mLargeModeLayout.setVisibility(View.VISIBLE);

        mIsShowing = true;
        int orientation = mCameraExt.getOrientation();
        operateOrientation(orientation);
    }

    private void stopShow() {
        Log.v(TAG, "stopShow");
        mCameraExt.setTopBarVisible(0);
        if (mLargeModeLayout != null && mRootView != null) {
            mRootView.removeView(mLargeModeLayout);
            mLargeModeLayout.destroyDrawingCache();
            mLargeModeLayout = null;
        }
        mCameraExt.setBottomBarVisible(View.VISIBLE);
        mCameraExt.setTopBarVisible(View.VISIBLE);
        // mCameraExt.setTopBarBackgroudcolor(-1);
        mHandler.sendEmptyMessage(MSG_LEAVE_OPERATE_LAYER);
        mIsShowing = false;
    }

    private void findView(ViewGroup rootView) {
        if (mLargeModeLayout == null) {
            mLargeModeLayout = (LargeModelPreview) mInflater.inflate(R.layout.large_mode_layout,
                    null);
            mTopImageMask = (ImageView) mLargeModeLayout.findViewById(R.id.largemode_mask_top);
            mBottomImageMask = (ImageView) mLargeModeLayout
                    .findViewById(R.id.largemode_mask_bottom);
            mVerticalImageTip = (ImageView) mLargeModeLayout.findViewById(R.id.vertical_screen_tip);
            mHScreenLayout = (RelativeLayout) mLargeModeLayout
                    .findViewById(R.id.horizontal_screen_layout);
            mShutter = mLargeModeLayout.findViewById(R.id.shutter);
            mShutter.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    mCameraExt.onShutter();
                }
            });

            Point mPoint = new Point();

            mWindowManage.getDefaultDisplay().getSize(mPoint);
            int height = mPoint.y;

            int maskHeight = (int) (height * (1 / 1.78 - 1 / 2.35) / 2);

            LayoutParams paramTop = (LayoutParams) mTopImageMask.getLayoutParams();
            paramTop.height = maskHeight;
            mTopImageMask.setLayoutParams(paramTop);
            LayoutParams paramBottom = (LayoutParams) mBottomImageMask.getLayoutParams();
            paramBottom.height = maskHeight;
            mBottomImageMask.setLayoutParams(paramBottom);

            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                    RelativeLayout.LayoutParams.MATCH_PARENT,
                    RelativeLayout.LayoutParams.WRAP_CONTENT);
            lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
            rootView.addView(mLargeModeLayout, lp);
        }
    }

    private void addListener() {
        mLargeModeLayout.setOnTouchListener(this);
    }

    public void onOrientationChanged(int orientation) {
        operateOrientation(orientation);
    }

    public void operateOrientation(int orientation) {
        int mRotattion = getDisplayRotation();
        int mRotattionFlag = mRotattion / 90 % 2;
        int mOrientationFlag = orientation / 90 % 2;
        if (mLargeModeLayout != null && mIsShowing) {
            if ((mRotattionFlag ^ mOrientationFlag) == 1) {
                mHScreenLayout.setVisibility(View.VISIBLE);
                mVerticalImageTip.setVisibility(View.GONE);
                mCameraExt.setTopBarVisible(View.GONE);
                isViertical = false;
                hideOperateLayer();
            } else {
                mCameraExt.setTopBarVisible(View.VISIBLE);
                mVerticalImageTip.setVisibility(View.VISIBLE);
                mHScreenLayout.setVisibility(View.GONE);
                showOperateLayer();
                isViertical = true;
            }
            mLargeModeLayout.setOrientation(orientation, false);
        }
    }

    @Override
    public void onClick(View view) {

    }

    private void setEnabled(boolean enable) {
    }

    public void fade(boolean faded) {
        if (mLargeModeLayout == null) {
            return;
        }
        float alpha = 1;
        if (faded) {
            alpha = PREVIEW_FADE_ALPHA;
            setEnabled(false);
        } else {
            setEnabled(true);
        }
        mLargeModeLayout.setAlpha(alpha);
    }

    public void refactor() {
        Log.i(TAG, "refactor");
        mLargeModeLayout = null;
        mIsShowing = false;
    }

    public void resume() {

    }

    /**
     * Whether affect watermark
     * 
     * @return
     */
    public boolean isOn() {
        return mIsShowing;
    }

    private void initFullscreenRatio() {
        mFullScreenRatio = 4d / 3;
        DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
        double fullscreen;

        if (metrics.widthPixels > metrics.heightPixels) {
            fullscreen = (double) metrics.widthPixels / metrics.heightPixels;
        } else {
            fullscreen = (double) metrics.heightPixels / metrics.widthPixels;
        }

        for (int i = 0; i < RATIOS.length; i++) {
            if (Math.abs(RATIOS[i] - fullscreen) < Math.abs(fullscreen - mFullScreenRatio)) {
                mFullScreenRatio = RATIOS[i];
            }
        }

        Log.i(TAG, "findFullscreenRatio: find = " + mFullScreenRatio);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouch(View v, MotionEvent e) {
        if (isOperateLayerShow) {
            hideOperateLayer();
            return false;
        }

        int action = e.getActionMasked();
        e.getX();
        e.getY();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                showOperateLayer();
                return false;
            case MotionEvent.ACTION_UP:
                break;
            case MotionEvent.ACTION_MOVE: {
                break;
            }
            case MotionEvent.ACTION_CANCEL:
                break;

            default:
                return false;
        }
        return false;
    }

    public void showOperateLayer() {
        mHandler.sendEmptyMessage(MSG_SHOW_OPERATE_LAYER);
    }

    public void hideOperateLayer() {
        mHandler.removeMessages(MSG_HIDE_OPERATE_LAYER);
        mHandler.sendEmptyMessageDelayed(MSG_HIDE_OPERATE_LAYER, SHOW_TIMEOUT_TIME);
    }

    public void close() {
        stopShow();
    }

    public Handler getHander() {
        return mHandler;
    }

    public void show(ViewGroup root) {
        mRootView = root;
        startShow(root);
    }

    public void hide() {
        stopShow();
    }

    public int getDisplayRotation() {
        int rotation = mWindowManage.getDefaultDisplay().getRotation();
        switch (rotation) {
            case Surface.ROTATION_0:
                return 0;
            case Surface.ROTATION_90:
                return 90;
            case Surface.ROTATION_180:
                return 180;
            case Surface.ROTATION_270:
                return 270;
        }
        return 0;
    }

}
